
/*
 * Java class "Gunner.java" generated from Poseidon for UML.
 * Poseidon for UML is developed by <A HREF="http://www.gentleware.com">Gentleware</A>.
 * Generated with <A HREF="http://jakarta.apache.org/velocity/">velocity</A> template engine.
 */
package jcs;

import java.lang.String;
import robocode.Bullet;
import robocode.BulletHitEvent;


/**
 * <p></p>
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fd5]
 */
public class Gunner {

  ///////////////////////////////////////
  // attributes


/**
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fd4]
 */
    private long lastTick; 

/**
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fd3]
 */
    private double bulletPower; 

/**
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fd0]
 */
    private final double GUNTOLERANCE = 0.1; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffef686712:-7fce]
 */
    private final double ENERGY_BUFFER = 0.1; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$48ccb8:fff4562626:-7ff6]
 */
    private final double TARGET_BUFFER = 100.0; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7fe3]
 */
    private Bullet[] bullets; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f71]
 */
    private int gunMode = 0; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f6f]
 */
    private final int NUM_GUN_MODES = 4; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f6d]
 */
    private int[] bulletsMode; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f6b]
 */
    private int nextBulletIndex = 0; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f6a]
 */
    private final int BULLETS_LENGTH = 20; 

   ///////////////////////////////////////
   // associations

/**
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fce]
 */
    private Enemy currentTarget; 
/**
 * <p></p>
 * @poseidon-object-id [sm$3cc05f:ffef686712:-7ff2]
 */
    public Seth seth; 
/**
 * <p></p>
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f64]
 */
    public TargetingMode targeting; 


  ///////////////////////////////////////
  // operations


/**
 * 
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fcd]
 * @return 
 * @param _seth 
 */
    public  Gunner(Seth _seth) {        
        		seth = _seth;
        		lastTick = -100;
        		currentTarget = null;
        		seth.setAdjustGunForRobotTurn(true);
        		seth.setAdjustRadarForGunTurn(true);
                        targeting = new LinearTargeting(seth);
                        bullets = new Bullet[BULLETS_LENGTH];
                        bulletsMode = new int[BULLETS_LENGTH];
    } // end Gunner        

/**
 * 
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fcc]
 */
    public void doShoot() {        
                  double gunLeadAngle = 0.0;
        	  double temp;
                  if(seth.getEnemyList().getCount() > 0 && seth.getEnergy() > ENERGY_BUFFER)
                  {
                          if((seth.getTicks() - lastTick) > 12)
          		  {
          			lastTick = seth.getTicks();
          			reaquireTarget(); 					
          		  }
          		  bulletPower = targeting.calcBulletPower(currentTarget);
                	  double time = currentTarget.getCoord().calcDist( seth.getCurrentPos() ) / (20.0 - 3 * bulletPower);
                          gunLeadAngle = targeting.calcPoint(currentTarget, time);
                          double turnAmount = gunLeadAngle - seth.getGunHeadingRadians();
                          
                          if(turnAmount > 0.0 && turnAmount <= Math.PI)
                          {
                              seth.setTurnGunRightRadians(Math.abs(turnAmount));
                          }
                          else if(turnAmount > 0.0 && turnAmount > Math.PI)
                          {
                              seth.setTurnGunLeftRadians(Math.abs(turnAmount));
                          }
                          else if(turnAmount < 0.0 && turnAmount > -Math.PI)
                          {
                              seth.setTurnGunLeftRadians(Math.abs(turnAmount));
                          }
                          else
                          {
                              seth.setTurnGunRightRadians(Math.abs(turnAmount));
                          }
                          
                          // Fire at will!
                          if((seth.getGunHeat() < (seth.getGunCoolingRate()/5)) && (Math.abs(seth.getGunHeadingRadians() - gunLeadAngle) < GUNTOLERANCE))
          		  {
                                // Fire and save the bullet
                                addBullet(seth.fireBullet(bulletPower));
                                currentTarget.incrementShots(gunMode);
          			setGunMode();
                                System.out.println("power = "+bulletPower);
          		  }
               	}
    } // end doShoot        

/**
 * 
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7fcb]
 */
    public void reaquireTarget() {        
        			int targetIndex = 0;
        			Enemy[] enemies = seth.getEnemyList().getEnemies();
        			for(int i = 0; i < seth.getEnemyList().getCount(); i++)
        			{
        				double diff = seth.getCurrentPos().calcDist(enemies[targetIndex].getCoord()) - seth.getCurrentPos().calcDist(enemies[i].getCoord());
                                            if( (diff > 0.0 && (enemies[targetIndex].getEnergy() >  enemies[i].getEnergy()) )  ||  diff > TARGET_BUFFER) 
        					targetIndex = i;
        			}
        			currentTarget = enemies[targetIndex];
    } // end reaquireTarget        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$3cc05f:ffef686712:-7fd7]
 * @return 
 */
    public String getTargetName() {        
        return currentTarget.getName();
    } // end getTargetName        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f70]
 */
    public void setGunMode() {        
        int gun = 0;
        for(int i = 0; i < (NUM_GUN_MODES /*-1*/) ; i++)
        {
        	System.out.println("gun : " + i + ", ratio = " + currentTarget.getRatio(i));
            if(currentTarget.getRatio(i) > currentTarget.getRatio(gun))
                gun = i;
        }
        gunMode = gun;
        targeting = currentTarget.getGun(gun);          
    } // end setGunMode        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f6e]
 * @param e 
 */
    public void bulletHitEvent(BulletHitEvent e) {        
        for(int i=0; i < bullets.length; i++)
        {
            if(e.getBullet() == bullets[i] && currentTarget != null)
            {
                currentTarget.incrementHit(bulletsMode[i]);
                //System.out.println("HIT " + e.getName() + " using mode " + i );
            }
        }
    } // end bulletHitEvent        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$aaca8a:ffff2170b8:-7f6c]
 * @param _bullet 
 */
    public void addBullet(Bullet _bullet) {        
        bullets[nextBulletIndex] = _bullet;
        bulletsMode[nextBulletIndex] = gunMode;
        if(nextBulletIndex == (BULLETS_LENGTH-1))
            nextBulletIndex = 0;
        else
            nextBulletIndex++;
    } // end addBullet        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$aaa392:10004e10e23:-7f95]
 * @return 
 */
    public Enemy getCurrentTarget() {        
        return currentTarget;
    } // end getCurrentTarget        

 } // end Gunner


